﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using HtmlAgilityPack;
using PromoOffersCrawler.Crawler.Utils;
using PromoOffersCrawler.Crawler.ExtensionMethods;

namespace PromoOffersCrawler.Crawler.Managers
{
    public class OfferAnalyzer
    {
        private HtmlNode offerRoot;
        private HtmlAnalyzer html;
        private Dictionary<string, string> knowledge;

        public OfferAnalyzer(HtmlAnalyzer html, Dictionary<string, string> knowledge)
        {
            this.html = html;
            this.offerRoot = html.GetNode(knowledge[Constants.OfferDetailsRootElementName]);
            this.knowledge = knowledge;

        }
        /// <summary>
        /// Persists the name of the offer
        /// </summary>
        /// <returns></returns>
        public string GetName()
        {
            if (knowledge.ContainsKey(Constants.ExplicitTytleTagType))
            {
                return html.GetAllDescedantOf(Constants.OfferDetailsRootElementName, knowledge[Constants.ExplicitTytleTagType]).FirstOrDefault().InnerText.RemoveHtml().Trim();
            }
            else
            {
                return GetFirstHeaderTag().InnerText.RemoveHtml().Trim();
            }
        }
        /// <summary>
        /// Persists the description of the current offer element
        /// </summary>
        /// <returns></returns>
        public string GetDescription()
        {
            if (!knowledge.ContainsKey(Constants.DescriptionPath))
            {
                var stringContents = offerRoot.SelectNodes(knowledge[Constants.PathToDescriptionParrent]).Select(x => x.InnerText.RemoveHtml().Trim());
                int maxLenght = stringContents.Max(y => y.Length);
                return stringContents.FirstOrDefault(x => x.Length == maxLenght);
            }
            else
            {
                var stringContents = offerRoot.SelectNodes(knowledge[Constants.DescriptionPath]).Select(x => x.InnerText.RemoveHtml().Trim());
                string result = null;
                foreach (var stringContent in stringContents)
                {
                    result += stringContent;
                }
                return result;

            }

        }
        /// <summary>
        /// Persists the price of the current offer
        /// </summary>
        /// <returns></returns>
        public decimal GetPrice()
        {
            if (!knowledge.ContainsKey(Constants.PricePathExact))
            {
                string fullString = offerRoot.SelectSingleNode(knowledge[Constants.PricePathFromRoot]).InnerText;
                string numberString = Regex.Match(fullString, @"\d+").Value;
                return decimal.Parse(numberString);
            }
            else
            {
                var priceElem = html.GetSingleElementByPath(knowledge[Constants.PricePathExact]);
                var priceString = priceElem.InnerHtml;
                string decimalSeparator = System.Threading.Thread.CurrentThread.CurrentCulture.NumberFormat.CurrencyDecimalSeparator;
                if (knowledge.ContainsKey(Constants.PriceExplicitDecimalSeparator))
                {
                    priceString = priceString.Replace(knowledge[Constants.PriceExplicitDecimalSeparator], decimalSeparator).RemoveHtml().Trim();
                }
                var regexPrice = Regex.Match(priceString, @"(\d+)" + decimalSeparator + @"(\d+)").Value;
                if (string.IsNullOrEmpty(regexPrice))
                {
                    regexPrice = Regex.Match(priceString, @"(\d+)").Value;
                }
                return decimal.Parse(regexPrice);
            }
        }

        /// <summary>
        /// Returns the first header tag direct descedant of the offer root. Starts from h1 and stop attempts to find such at h7. hi is with higher priority from hj in case i is less than j
        /// </summary>
        /// <param name="tagId"></param>
        /// <returns></returns>
        public HtmlNode GetFirstHeaderTag()
        {
            HtmlNode result = null;
            for (int i = 1; i <= 7; i++)
            {
                string tag = "h" + i;
                result = this.offerRoot.SelectSingleNode(".//" + tag);
                if (result != null)
                {
                    return result;
                }
            }
            return result;
        }
    }
}
